﻿//#define UseHybridECS
using UnityEngine;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;

namespace Jinndev.ECS {

    public static class ECSManager {

        private static EntityManager entityManager;

        /// <summary>
        /// 如果没有指定过，则默认使用World.DefaultGameObjectInjectionWorld.EntityManager
        /// </summary>
        public static EntityManager EntityManager {
            get {
                if (!entityManager.World.IsCreated) {
                    entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
                }
                return entityManager;
            }
        }

        /// <summary>
        /// 指定EntityManager
        /// </summary>
        /// <param name="entityManager"></param>
        public static void Init(EntityManager entityManager) {
            ECSManager.entityManager = entityManager;
        }

        public static void Dispose() {
            
        }

        public static T GetOrCreateSystem<T>() where T : ComponentSystemBase {
            return EntityManager.World.GetOrCreateSystem<T>();
        }

        public static T GetExistingSystem<T>() where T : ComponentSystemBase {
            return EntityManager.World.GetExistingSystem<T>();
        }

        public static void AddComponent<T>(Entity entity) {
            ECSUtil.SafeAddComponent<T>(EntityManager, entity);
        }

        public static void SetComponentData<T>(Entity entity, T data) where T : struct, IComponentData {
            ECSUtil.SafeSetComponentData(EntityManager, entity, data);
        }

        public static bool TryGetComponentData<T>(Entity entity, out T component) where T : struct, IComponentData {
            return ECSUtil.TryGetComponentData(EntityManager, entity, out component);
        }

        public static bool TryGetSharedComponentData<T>(Entity entity, out T component) where T : struct, ISharedComponentData {
            return ECSUtil.TryGetSharedComponentData(EntityManager, entity, out component);
        }

        public static DynamicBuffer<T> GetBuffer<T>(Entity entity) where T : struct, IBufferElementData {
            return ECSUtil.GetOrAddBuffer<T>(EntityManager, entity);
        }

        public static Entity CreateChildEntity(Entity entity, EntityArchetype archetype) {
            return ECSUtil.CreateChildEntity(EntityManager, entity, archetype);
        }

        public static Entity GetParent(Entity entity) {
            return ECSUtil.TryGetParent(EntityManager, entity);
        }

        public static void SetTranslation(Entity entity, float3 position) {
            ECSUtil.SetTranslation(EntityManager, entity, position);
        }

        public static void SetLocaltoWorld(Entity entity, float3 position) {
            ECSUtil.SetLocaltoWorld(EntityManager, entity, position);
        }

        public static void DestroyEntities(EntityArchetype archetype) {
            NativeArray<ComponentType> types = archetype.GetComponentTypes(Allocator.Temp);
            EntityQuery query = EntityManager.CreateEntityQuery(types.ToArray());
            types.Dispose();
            EntityManager.DestroyEntity(query);
        }


        public static void DestroyEntities(params ComponentType[] requiredComponents) {
            EntityQuery query = EntityManager.CreateEntityQuery(requiredComponents);
            EntityManager.DestroyEntity(query);
        }

        public static void DestroyEntities<T>() {
            EntityQuery query = EntityManager.CreateEntityQuery(typeof(T));
            EntityManager.DestroyEntity(query);
        }


        //public static void DestroyEntitiesWithChildren<T>() {
        //    EntityQuery query = EntityManager.CreateEntityQuery(typeof(T));
        //    DestroyEntitySystem.DestroyEntities(EntityManager, query, true);
        //}

        public static void SetName(Entity entity, string name) {
            // Entities 0.14版本有bug，多次调用会报错
//#if UNITY_EDITOR
//            try {
//                EntityManager.SetName(entity, name);
//            }
//            catch(System.Exception e) {
//                Debug.LogError(e.Message);
//            }
//#endif
        }

    }

}
